﻿''' <summary>
''' This class implements a registry collector.
''' </summary>
''' <remarks>
''' The RegistryCollector's purpose is to read all registry entries of
''' specified keys and include them in the system info report. This
''' collector can be used to report on parameters saved in the registry
''' or registry values that can reveal the presence or absence of 
''' specific software.
''' </remarks>
Public Class RegistryCollector
    Implements ICollector

    ''' <summary>
    ''' List of writers passed when Startup() is called.
    ''' </summary>
    ''' <remarks></remarks>
    Protected m_writers As List(Of Writer.IWriter)

    ''' <summary>
    ''' List of registry entries to be collected.
    ''' </summary>
    ''' <remarks></remarks>
    Protected m_entries As List(Of RegistryEntry)

    ''' <summary>
    ''' This holds an error description.
    ''' </summary>
    ''' <remarks></remarks>
    Protected m_error As String

    Public Sub Cleanup() Implements ICollector.Cleanup

        'Nothing to do 

    End Sub

    Public Sub Run() Implements ICollector.Run

        'Write our category name.
        Writer.WritersHelper.WriteCategory("Registry Information", m_writers)

        'If an error occurred while reading the configuration file, write
        'it out and stop here.
        If m_error <> "" Then
            Writer.WritersHelper.WriteCategoryError(m_error, m_writers)
        Else
            'Scan all registry entries.
            For Each key As RegistryEntry In m_entries
                Try
                    'Write our key.
                    Writer.WritersHelper.WriteSection(key.Name, m_writers)

                    'Get the registry key.
                    Dim rk As Microsoft.Win32.RegistryKey = Nothing
                    Dim section As String = key.Location.Substring(0, 5).ToUpper()
                    Select Case section
                        Case "HKLM\"
                            rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(key.Location.Substring(5))
                        Case "HKUS\"
                            rk = Microsoft.Win32.Registry.Users.OpenSubKey(key.Location.Substring(5))
                        Case "HKCC\"
                            rk = Microsoft.Win32.Registry.CurrentConfig.OpenSubKey(key.Location.Substring(5))
                        Case "HKCR\"
                            rk = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(key.Location.Substring(5))
                    End Select

                    'Found the key?
                    If rk Is Nothing Then
                        Writer.WritersHelper.WriteEntry("No key found", m_writers)
                    Else
                        'Loop for all entries under this key.
                        Dim s() As String = rk.GetValueNames()
                        For i As Integer = 0 To s.GetUpperBound(0)
                            Writer.WritersHelper.WriteEntry(s(i), Convert.ToString(rk.GetValue(s(i))), m_writers)
                        Next
                    End If
                Catch ex As Exception
                    'Error gathering key info.
                    Writer.WritersHelper.WriteSectionError("Error gathering info for key " + key.Name, m_writers)
                End Try
                'Write out a blank.
                Writer.WritersHelper.WriteBlank(m_writers)
            Next
        End If

    End Sub

    Public Sub Startup(ByVal cfgFile As String, ByVal writers As System.Collections.Generic.List(Of Writer.IWriter)) Implements ICollector.Startup

        'Get all writers.
        m_writers = writers
        'Read configuration file.
        ReadConfiguration(cfgFile)

    End Sub

    ''' <summary>
    ''' Reads the configuration file.
    ''' </summary>
    ''' <param name="fName">File name with registry collector configuration.</param>
    ''' <remarks></remarks>
    Protected Sub ReadConfiguration(ByVal fName As String)

        Const REGISTRYSECTION_TABLE As String = "RegistrySection"

        Try
            'Read in a dataset.
            Dim ds As New DataSet
            ds.ReadXml(fName)
            m_entries = New List(Of RegistryEntry)

            'Parse all entries.
            For i As Integer = 0 To ds.Tables(REGISTRYSECTION_TABLE).Rows.Count - 1
                With ds.Tables(REGISTRYSECTION_TABLE).Rows(i)
                    m_entries.Add(New RegistryEntry(Convert.ToString(.Item("Name")), Convert.ToString(.Item("Location"))))
                End With
            Next
            ds.Dispose()
            ds = Nothing

            'Signal no error.
            m_error = ""
        Catch ex As Exception
            'Keep the error here.
            m_error = ex.ToString()
        End Try

    End Sub

End Class
